#include "Application.h"
#include "../scion_utilities/SDL_Wrappers.h"
#include <SDL3/SDL.h>
#include <glad/glad.h>
#include "../scion_utilities/hzpch.h"
#include "Log.h"
#include <string>
#include <SOIL2.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "Rendering/Essentials/ShaderLoader.h"
#include "Rendering/Essentials/TextureLoader.h"
#include "Rendering/Core/Camera2D.h"
#include "Rendering/Essentials/Vertex.h"
#include "entt/entt.hpp"
#include "core/ECS/Components/SpriteComponent.h"
#include "core/ECS/Components/TransfomComponet.h"
#include "core/ECS/Components/Identification.h"
#include "core/ECS/Entity.h"
#include "core/Resources/AssetManager.h"
#include "core/Systems/ScriptSystem.h"
#include "sol/sol.hpp"
#include "core/Systems/RenderSystem.h"

namespace SCION_EDITOR
{
  bool Application::Initialize()
  {
    SCION_UTIL::testLog();

    //  使用正确的SDL初始化标志
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) == 0)
    {
      std::string error = SDL_GetError();
      SCION_ERROR("Failed to initialize SDL: " + error);
      return false;
    }

    // 检查视频驱动
    const char *video_driver = SDL_GetCurrentVideoDriver();
    if (!video_driver)
    {
      SCION_ERROR("No video driver available!");
      SDL_Quit();
      return false;
    }
    SCION_INFO("Current video driver: " + std::string(video_driver));

    // set up OpenGL
    if (SDL_GL_LoadLibrary(NULL) == 0)
    {
      std::string error = SDL_GetError();
      SCION_ERROR("Failed to Open GL Library: " + error);
      SDL_Quit();
      return false;
    }

    // 设置opengl属性
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

    // 设置每个通道的位数
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 4);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);

    // 创建窗口
    m_pWindow = std::make_unique<SCION_WINDOWING::Window>(
        "Test Window",
        960,
        720,
        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        true,
        SDL_WINDOW_OPENGL);

    if (!m_pWindow->GetWindow())
    {
      SCION_ERROR("Failed to create window!");
      SDL_Quit();
      return false;
    }

    // 创建opengl上下文
    m_pWindow->SetGLContext(SDL_GL_CreateContext(m_pWindow->GetWindow().get()));

    if (!m_pWindow->GetGLContext())
    {
      std::string error = SDL_GetError();
      SCION_ERROR("Falied to create openGl context: " + error);
      SDL_Quit();
      return false;
    }

    SDL_GL_MakeCurrent(m_pWindow->GetWindow().get(), m_pWindow->GetGLContext());
    SDL_GL_SetSwapInterval(1);

    // 修正glad初始化检查
    if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
    {
      SCION_ERROR("Failed to LoadGl ----> GLAD");
      SDL_Quit();
      return false;
    }

    // 修正OpenGL信息日志 - 直接传递字符串指针
    const char *glVersion = (const char *)glGetString(GL_VERSION);
    const char *glslVersion = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
    const char *glVendor = (const char *)glGetString(GL_VENDOR);
    const char *glRenderer = (const char *)glGetString(GL_RENDERER);

    if (glVersion)
      SCION_INFO("OpenGL Version: " + std::string(glVersion));
    if (glslVersion)
      SCION_INFO("GLSL Version: " + std::string(glslVersion));
    if (glVendor)
      SCION_INFO("Vendor: " + std::string(glVendor));
    if (glRenderer)
      SCION_INFO("Renderer: " + std::string(glRenderer));

    // 启用alpha blending
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    // 资产管理器
    auto assetManager = std::make_shared<SCION_RESOURCES::AssetManager>();
    if (!assetManager)
    {
      SCION_ERROR(fmt::format("Failed to create the asset manager!"));
      return false;
    }
    if (!assetManager->AddTexture("castle", "./assets/textures/castle.png", true))
    {
      SCION_ERROR(fmt::format("Failed to create and add the texture"));
      return false;
    }
    // 添加纹理
    auto texture = assetManager->GetTexture("castle");

    // 创建UVs 坐标
    SCION_INFO("Loaded Texture,width: " + std::to_string(texture.GetWidht()) + "," + "height: " + std::to_string(texture.GetHeight()));
    SCION_WARN("Loaded Texture,width: " + std::to_string(texture.GetWidht()) + "," + "height: " + std::to_string(texture.GetHeight()));

    // 创建一个新实体 UVs
    // 创建一个注册表
    m_pRegistry = std::make_unique<SCION_CORE::ECS::Registry>();
    if (!m_pRegistry)
    {
      SCION_ERROR("Failed to create the entt registry!");
      return false;
    }
    SCION_CORE::ECS::Entity entity1{*m_pRegistry, "Ent1", "Test"};

    auto &transform = entity1.AddComponent<SCION_CORE::ECS::TransformComponent>(
        SCION_CORE::ECS::TransformComponent{
            glm::vec2(1.f, 1.f),   // position
            glm::vec2(0.5f, 0.5f), // scale
            0.f                    // rotation
        }

    );

    auto &sprite = entity1.AddComponent<SCION_CORE::ECS::SpriteComponent>(
        SCION_CORE::ECS::SpriteComponent{
            16.f,                                       // width
            16.f,                                       // height
            SCION_RENDERING::Color{255, 100, 100, 255}, // 改为浅红色
            // SCION_RENDERING::Color{0, 255, 0, 255}, 绿色
            0,  // start_x
            28, // start_y
            0,
            "castle"}

    );
    // 生成 UV 坐标
    sprite.generate_uvs(texture.GetWidht(), texture.GetHeight());

    auto &identid = entity1.GetComponent<SCION_CORE::ECS::Identification>();
    SCION_INFO(fmt::format("Name:{},Group:{},ID:{}", identid.name, identid.group, identid.entity_id));

    // 创建一个lua state
    auto lua = std::make_shared<sol::state>();
    if (!lua)
    {
      SCION_ERROR("Failed to create the lua state!");
      return false;
    }
    lua->open_libraries(sol::lib::base, sol::lib::math, sol::lib::os, sol::lib::string, sol::lib::table);
    if (!m_pRegistry->AddToContext<std::shared_ptr<sol::state>>(lua))
    {
      SCION_ERROR("Failed to add the lua state to the registry context!");
      return false;
    }
    // 创建脚本系统
    SCION_CORE::Systems::ScriptSystem scriptSystem{*m_pRegistry};
    if (!scriptSystem.LoadMainCript(*lua))
    {
      SCION_ERROR("Failed to load the main.lua script!");
      return false;
    }
    if (!scriptSystem.LoadMainCript(*lua))
    {
      SCION_ERROR("Failed to load the main.lua script!");
      return false;
    }

    if (!m_pRegistry->AddToContext<std::shared_ptr<SCION_CORE::Systems::ScriptSystem>>(std::make_shared<SCION_CORE::Systems::ScriptSystem>(scriptSystem)))
    {
      SCION_ERROR("Failed to add the script system to the registry context!");
      return false;
    }

    auto renderSystem = std::make_shared<SCION_CORE::Systems::RenderSystem>(*m_pRegistry);
    if (!renderSystem)
    {
      SCION_ERROR("Failed to create the render system!");
      return false;
    }

    if (!m_pRegistry->AddToContext<std::shared_ptr<SCION_CORE::Systems::RenderSystem>>(renderSystem))
    {
      SCION_ERROR("Failed to add th render system to the registry context!");
      return false;
    }

    // 创建一个相机
    auto camera = std::make_shared<SCION_RENDERING::Camera2D>();
    camera->SetScale(2.f);

    // 将相机和资产管理器添加到上下文中
    if (!m_pRegistry->AddToContext<std::shared_ptr<SCION_RESOURCES::AssetManager>>(assetManager))
    {
      SCION_ERROR("Failed to add the asset manager to the registry context!");
      return false;
    }
    if (!m_pRegistry->AddToContext<std::shared_ptr<SCION_RENDERING::Camera2D>>(camera))
    {
      SCION_ERROR("Failed to add the camera2D to the registry context!");
      return false;
    }

    if (!LoadShader())
    {
      SCION_ERROR("Failed to load the shaders!");
      return false;
    }

    return true;
  }
  bool Application::LoadShader()
  {
    auto assetManager = m_pRegistry->GetContext<std::shared_ptr<SCION_RESOURCES::AssetManager>>();
    if (!assetManager->AddShader("basic", "assets/shaders/basicShader.vert", "assets/shaders/basicShader.frag"))
    {
      SCION_ERROR("Failed to add thee the shader to the asset manager");
      return false;
    }

    // 顶点着色器 - 添加纹理坐标
    auto shader = SCION_RENDERING::ShaderLoader::Create("assets/shaders/basicShader.vert", "assets/shaders/basicShader.frag");
    if (!shader)
    {
      SCION_ERROR("Filed to create the shader!");
      return false;
    }
    return true;
  }
  void Application::ProcessEvent()
  {
    while (SDL_PollEvent(&m_Event))
    {
      switch (m_Event.type)
      {
      case SDL_EVENT_QUIT:
        m_bIsRunning = false;
        break;
      case SDL_EVENT_KEY_DOWN:
        SCION_INFO("Key pressed - Scancode: " + std::to_string(m_Event.key.scancode) +
                   ", Keycode: " + std::to_string(m_Event.key.key));
        // 按ESC 键退出
        if (m_Event.key.key == SDLK_ESCAPE)
        {
          SCION_INFO("SDLK_ESCAPE , EXIT.");
          m_bIsRunning = false;
        }

        break;
      case SDL_EVENT_MOUSE_BUTTON_DOWN:
        // 点击鼠标推出
        SCION_INFO("SDL_EVENT_MOUSE_BUTTON_DOWN , EXIT.");
        m_bIsRunning = false;
        break;
      default:
        break;
      }
    }
  }
  void Application::Update()
  {
    auto &camera = m_pRegistry->GetContext<std::shared_ptr<SCION_RENDERING::Camera2D>>();
    if (!camera)
    {
      SCION_ERROR("Failed to get the camera from the registry context!");
      return;
    }
    camera->update();

    auto &scriptSystem = m_pRegistry->GetContext<std::shared_ptr<SCION_CORE::Systems::ScriptSystem>>();
    scriptSystem->Update();

    auto view = m_pRegistry->GetRegistry().view<SCION_CORE::ECS::TransformComponent, SCION_CORE::ECS::SpriteComponent>();
    static float rotation{0.f};
    static float x_pos{10.f};
    static bool bMoveRight{true};

    if (rotation >= 360.f)
    {
      rotation = 0.f;
    }
    if (bMoveRight && x_pos < 300.f)
    {
      x_pos += 3;
    }
    else if (bMoveRight && x_pos >= 300.f)
    {
      bMoveRight = false;
    }
    if (!bMoveRight && x_pos > 10.f)
    {
      x_pos -= 3;
    }
    else if (!bMoveRight && x_pos <= 10.f)
    {
      bMoveRight = true;
    }
    for (const auto &entity : view)
    {
      SCION_CORE::ECS::Entity ent{*m_pRegistry, entity};
      auto &transform = ent.GetComponent<SCION_CORE::ECS::TransformComponent>();

      transform.position.x = x_pos;
      transform.rotation = rotation;
    }

    rotation += bMoveRight ? 9 : -9;
  }
  void Application::Render()
  {
    auto &renderSystem = m_pRegistry->GetContext<std::shared_ptr<SCION_CORE::Systems::RenderSystem>>();

    // 使用正确的视口设置
    int width, height;
    SDL_GetWindowSize(m_pWindow->GetWindow().get(), &width, &height);
    glViewport(0, 0, width, height);

    // 将黑色改为白色：glClearColor(0.f, 0.f, 0.f, 1.f) → glClearColor(1.f, 1.f, 1.f, 1.f)
    glClearColor(1.f, 1.f, 1.f, 1.f); // 改为白色背景
    glClear(GL_COLOR_BUFFER_BIT);

    auto &scriptSystem = m_pRegistry->GetContext<std::shared_ptr<SCION_CORE::Systems::ScriptSystem>>();
    scriptSystem->Render();
    renderSystem->Update();

    SDL_GL_SwapWindow(m_pWindow->GetWindow().get());
  }
  void Application::Clear()
  {
    // 清理资源
    auto &assetManager = m_pRegistry->GetContext<std::shared_ptr<SCION_RESOURCES::AssetManager>>();
    const auto &texture = assetManager->GetTexture("castle");
    auto id = texture.GetID();
    glDeleteTextures(1, &id);

    SDL_Quit();
  }
  Application::Application() : m_pWindow{nullptr}, m_pRegistry{nullptr}, m_Event{}, m_bIsRunning{true}
  {
  }
  Application &Application::GetInstance()
  {
    static Application app{};
    return app;
  }
  Application::~Application()
  {
  }
  void Application::Run()
  {
    if (!Initialize())
    {
      SCION_ERROR("Failed app is not Initialized!");
      return;
    }
    while (m_bIsRunning)
    {
      ProcessEvent();
      Update();
      Render();
    }
  }
}